#include "ring_buffer.h"

// Initialize ring buffer
void rb_init(ringbuf_t *rb, uint8_t *buf, uint16_t size)
{
    rb->buf = buf;
    rb->size = size;
    rb->mask = size - 1;  // must be power of 2
    rb->head = 0;
    rb->tail = 0;
}

// Put one byte into ring buffer
// Safe for single producer / single consumer scenario (ISR + main)
bool rb_put(ringbuf_t *rb, uint8_t data)
{
    uint16_t next = (rb->head + 1) & rb->mask;
    if (next == rb->tail) return false; // buffer full
    rb->buf[rb->head] = data;
    rb->head = next;
    return true;
}

// Get one byte from ring buffer
bool rb_get(ringbuf_t *rb, uint8_t *data)
{
    if (rb->head == rb->tail) return false; // buffer empty
    *data = rb->buf[rb->tail];
    rb->tail = (rb->tail + 1) & rb->mask;
    return true;
}

// Get number of bytes currently in buffer
uint16_t rb_count(ringbuf_t *rb)
{
    return (rb->head - rb->tail) & rb->mask;
}

// Check if buffer is empty
bool rb_is_empty(ringbuf_t *rb)
{
    return rb->head == rb->tail;
}

// Check if buffer is full
bool rb_is_full(ringbuf_t *rb)
{
    return ((rb->head + 1) & rb->mask) == rb->tail;
}